import { ElementPropertyConfig, KeyMap, PropertyEntity } from '@farris/ide-property-panel';
import { EditorTypes } from '@farris/ui-datagrid-editors';
import {
    BindingEditorComponent, BindingEditorConverter, CodeEditorComponent,
    ItemCollectionConverter, ItemCollectionEditorComponent, JavaScriptBooleanConverter, JavaScriptBooleanEditorComponent,
    StyleEditorComponent
} from '@farris/designer-devkit';
import { FormBindingType, GridFieldDataType } from '@farris/designer-services';
import { DgControl } from '../../../../../../utils/dg-control';
import { FormPropertyChangeObject } from '../../../../../../entity/property-change-entity';
import { CollectionProp } from '../../../../common/property/collection-property-config';
import { FieldStyleConfigComponent } from '../../../../common/property/editor/field-style-config/field-style-config.component';
import { EventsEditorFuncUtils } from '../../../../../../utils/events-editor-func';
import { GridFieldFormatterConverter } from '../../../../common/property/editor/grid-field-formatter-converter';

export class GridFieldProp extends CollectionProp {

    propertyConfig: ElementPropertyConfig[];


    getPropConfig(propertyData: any, gridData: any): ElementPropertyConfig[] {
        const viewModelId = this.viewModelId;

        this.propertyConfig = [];

        // 基本信息属性
        const basicPropConfig = this.getBasicPropConfig(propertyData, viewModelId, gridData);
        this.propertyConfig.push(basicPropConfig);

        // 快捷配置属性
        const fieldStyleConfig = this.getFieldStyleProperties(propertyData, viewModelId, gridData);
        this.propertyConfig.push(fieldStyleConfig);

        // 外观属性
        const appearancePropConfig = this.getAppearanceProperties(propertyData, viewModelId, gridData);
        this.propertyConfig.push(appearancePropConfig);

        // 行为属性
        const behaviorPropConfig = this.getBehaviorProperties(propertyData, viewModelId, gridData);
        this.propertyConfig.push(behaviorPropConfig);

        if (propertyData.controlSource === 'Farris') {
            // 分组合计属性
            const groypAggregateProperties = this.getGroupAggregateProperties(propertyData);
            this.propertyConfig.push(groypAggregateProperties);

            // 汇总合计属性
            const aggregateProperties = this.getAggregateProperties(propertyData);
            this.propertyConfig.push(aggregateProperties);
        }

        // 可编辑的列表：
        if (gridData.fieldEditable && propertyData.editor) {
            // 列编辑器属性
            const editorProp = this.getFieldEditorProp(propertyData);
            if (editorProp.length > 0) {
                this.propertyConfig = this.propertyConfig.concat(editorProp);
            }

            // 表达式属性
            const exprPropConfig = this.getExpressionPropConfig(propertyData.editor, viewModelId, 'gridFieldEditor');
            if (exprPropConfig) {
                this.propertyConfig.push(exprPropConfig);
            }
        } else {
            // 事件属性(标签超链，可编辑列表的标签超链属性与编辑器合并了，不再单独分类)
            const eventPropConfig = this.getEventPropertyConfig(propertyData, viewModelId);
            this.propertyConfig.push(eventPropConfig);
        }


        return this.propertyConfig;
    }

    private getBasicPropConfig(propertyData: any, viewModelId: string, gridData: any): ElementPropertyConfig {

        return {
            categoryId: 'basic',
            categoryName: '基本信息',
            properties: [
                {
                    propertyID: 'id',
                    propertyName: '标识',
                    propertyType: 'string',
                    description: '组件的id',
                    readonly: true
                },
                {
                    propertyID: 'caption',
                    propertyName: '标题',
                    propertyType: 'string',
                    description: '列标题名称'
                }
            ],
            setPropertyRelates(changeObject: FormPropertyChangeObject, prop, parameters?) {
                switch (changeObject.propertyID) {
                    case 'caption': {
                        if (propertyData.editor) {
                            propertyData.editor.title = changeObject.propertyValue;
                        }
                    }
                }
            },
        };
    }

    private getFieldStyleProperties(propertyData: any, viewModelId: string, gridData: any): ElementPropertyConfig {
        const self = this;
        return {
            categoryId: 'fieldStyleShortcutConfig',
            categoryName: '快捷配置',
            hide: !['date', 'datetime', 'enum', 'number'].includes(propertyData.dataType),
            properties: [
                {
                    propertyID: 'fieldStyleConfig',
                    propertyType: 'custom',
                    editor: FieldStyleConfigComponent,
                    editorParams: {
                        propertyData,
                        needClearConfig: false
                    },
                    description: '提供常用的日期、数字展示格式，提供带图标的枚举数据模板',
                    refreshPanelAfterChanged: true,
                }
            ],
            setPropertyRelates(changeObject: FormPropertyChangeObject, data, parameters: any) {
                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'fieldStyleConfig': {
                        // 数字、日期重置格式化属性
                        if (changeObject.propertyValue && changeObject.propertyValue.formatter) {
                            const formatterValue = changeObject.propertyValue.formatter;
                            Object.assign(propertyData.formatter, formatterValue);
                        }
                        // 枚举重置列模板属性
                        if (changeObject.propertyValue) {
                            propertyData.colTemplate = changeObject.propertyValue.colTemplate || '';

                            propertyData.iconConfigForEnumData = changeObject.propertyValue.enumIconConfig;

                            const fieldStyleConfig = this.properties.find((p: PropertyEntity) => p.propertyID === 'fieldStyleConfig');
                            fieldStyleConfig.editorParams.propertyData = propertyData;
                            fieldStyleConfig.editorParams.needClearConfig = false;
                        }
                        delete propertyData.fieldStyleConfig;


                        // 变更【外观分类】下的格式化属性
                        const currentAppearanceConfig = self.propertyConfig.find(cat => cat.categoryId === 'appearance');
                        const formatterProp = currentAppearanceConfig.properties.find(p => p.propertyID === 'formatter');
                        if (formatterProp) {
                            const newFormattterProps = self.getFormatterProps(propertyData);
                            Object.assign(formatterProp.cascadeConfig, newFormattterProps);
                        }

                        break;
                    }
                }
            }
        };
    }

    private getAppearanceProperties(propertyData: any, viewModelId: string, gridData: any): ElementPropertyConfig {
        const self = this;

        const formatterProps = this.getFormatterProps(propertyData);
        const appearanceProperties: PropertyEntity[] = [
            {
                propertyID: 'size',
                propertyName: '尺寸',
                propertyType: 'cascade',
                cascadeConfig: [
                    {
                        propertyID: 'width',
                        propertyName: '宽度（px）',
                        propertyType: 'number',
                        description: '组件的宽度',
                        min: 0,
                        decimals: 0
                    }
                ]
            },
            {
                propertyID: 'formatter',
                propertyName: '格式化',
                propertyType: 'cascade',
                cascadeConfig: formatterProps,
                visible: propertyData.controlSource === 'Farris',
                cascadeConverter: new GridFieldFormatterConverter()
            },
            {
                propertyID: 'captionTipContent',
                propertyName: '标题提示内容',
                propertyType: 'modal',
                description: '列标题提示信息的模板配置',
                editor: CodeEditorComponent,
                editorParams: {
                    language: 'html',
                    exampleCode: ''
                },
                visible: propertyData.controlSource === 'Farris'
            },
            {
                propertyID: 'captionTipStyler',
                propertyName: '标题提示样式',
                propertyType: 'modal',
                description: '列标题提示信息的样式设置',
                editor: StyleEditorComponent,
                showClearButton: true,
                visible: propertyData.controlSource === 'Farris'
            },
            {
                propertyID: 'showTips',
                propertyName: '显示单元格提示',
                propertyType: 'boolean',
                description: '是否显示单元格提示',
                visible: propertyData.controlSource === 'Farris',
                defaultValue: false
            },
            {
                propertyID: 'tipContent',
                propertyName: '单元格提示内容',
                propertyType: 'modal',
                description: '单元格提示内容设置',
                editor: CodeEditorComponent,
                visible: propertyData.showTips,
                editorParams: {
                    language: 'javascript',
                    exampleCode:
                        '(value, rowData, column) => {\r\n    return value + \'的提示\';\r\n}\r\n\r\n\r\n ' +
                        '注：\r\n  value：单元格数据  \r\n  rowData：行数据\r\n  column：列数据'
                }
            },
            {
                propertyID: 'tipMode',
                propertyName: '提示模式',
                propertyType: 'select',
                description: '提示模式选择',
                iterator: [
                    { key: 'allways', value: '鼠标滑过提示' },
                    { key: 'auto', value: '宽度不足时鼠标滑过提示' }
                ],
                visible: propertyData.showTips
            },
            {
                propertyID: 'styler',
                propertyName: '单元格样式',
                propertyType: 'modal',
                description: '单元格样式设置',
                editor: CodeEditorComponent,
                editorParams: {
                    language: 'javascript',
                    exampleCode:
                        '(value, rowData, rowIndex) => {\r\n    return {\r\n        style: {\r\n            \'color\': \'red\',\r\n' +
                        '            \'font-weight\': 800\r\n        }\r\n    };\r\n}\r\n\r\n\r\n注：\r\n  value：单元格数据  \r\n  ' +
                        'rowData：行数据  \r\n  rowIndex：当前行索引'
                },
                visible: propertyData.controlSource === 'Farris'
            },
            {
                propertyID: 'colTemplate',
                propertyName: '列模板',
                propertyType: 'modal',
                description: '列模板设置',
                editor: CodeEditorComponent,
                editorParams: {
                    language: 'html',
                    exampleCode: ''
                },
                visible: propertyData.controlSource === 'Farris',
                refreshPanelAfterChanged: true
            },
            {
                propertyID: 'textAlign',
                propertyName: '数据水平对齐方式',
                propertyType: 'select',
                description: '数据水平对齐方式选择',
                defaultValue: 'left',
                iterator: [{ key: 'left', value: '靠左' }, { key: 'right', value: '靠右' }, { key: 'center', value: '居中' }],
                visible: propertyData.controlSource === 'Farris'
            }, {
                propertyID: 'vAlign',
                propertyName: '数据垂直对齐方式',
                propertyType: 'select',
                description: '数据垂直对齐方式选择',
                defaultValue: 'middle',
                iterator: [{ key: 'top', value: '靠上' }, { key: 'middle', value: '居中' }, { key: 'bottom', value: '靠下' }],
                visible: propertyData.controlSource === 'Farris'
            }, {
                propertyID: 'hAlign',
                propertyName: '表头对齐方式',
                propertyType: 'select',
                description: '表头对齐方式选择',
                defaultValue: 'left',
                iterator: [{ key: 'left', value: '靠左' }, { key: 'right', value: '靠右' }, { key: 'center', value: '居中' }],
                visible: propertyData.controlSource === 'Farris'
            },
            {
                propertyID: 'headerStyler',
                propertyName: '表头样式',
                propertyType: 'modal',
                description: '表头样式设置',
                editor: StyleEditorComponent,
                showClearButton: true,
                visible: propertyData.controlSource === 'Farris'
            }
        ];

        return {
            categoryId: 'appearance',
            categoryName: '外观',
            properties: appearanceProperties,
            setPropertyRelates(changeObject: FormPropertyChangeObject, data, parameters: any) {
                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'linkedLabelEnabled': {
                        const linkedLabelClick = this.properties.find((p: PropertyEntity) => p.propertyID === 'linkedLabelClick');
                        if (linkedLabelClick) {
                            linkedLabelClick.visible = changeObject.propertyValue;
                        }
                        break;
                    }
                    case 'type': {
                        // 列格式化属性
                        if (changeObject.parentPropertyID === 'formatter') {
                            const formatter = this.properties.find(p => p.propertyID === 'formatter');
                            if (formatter && formatter.cascadeConfig) {
                                formatter.cascadeConfig.filter(p => p.group).forEach(p => {
                                    if (p.group === 'boolean') {
                                        p.visible = changeObject.propertyValue.indexOf(p.group) > -1;
                                    } else {
                                        p.visible = p.group === changeObject.propertyValue;
                                    }
                                });
                            }

                            propertyData.formatter = self.setDataGridFormatterDefaults(changeObject.propertyValue, propertyData.formatter);

                            // 联动修改列样式的快捷配置
                            const fieldStyleShortcutConfig = self.propertyConfig.find(c => c.categoryId === 'fieldStyleShortcutConfig');
                            if (fieldStyleShortcutConfig && fieldStyleShortcutConfig.properties && fieldStyleShortcutConfig.properties.length) {
                                const fieldStyleProp = fieldStyleShortcutConfig.properties.find(p => p.propertyID === 'fieldStyleConfig');
                                if (fieldStyleProp) {
                                    fieldStyleProp.editorParams.propertyData = propertyData;
                                }
                            }
                        }
                        break;
                    }
                    case 'showTips': {
                        const tipContent = this.properties.find(p => p.propertyID === 'tipContent');
                        if (tipContent) {
                            tipContent.visible = changeObject.propertyValue;
                        }
                        const tipMode = this.properties.find(p => p.propertyID === 'tipMode');
                        if (tipMode) {
                            tipMode.visible = changeObject.propertyValue;
                        }
                        break;
                    }
                    case 'colTemplate': {
                        // 联动修改列样式的快捷配置
                        self.clearIconConfigAfterColTemplateChanged(propertyData, changeObject, parameters);

                        const fieldStyleShortcutConfig = self.propertyConfig.find(c => c.categoryId === 'fieldStyleShortcutConfig');
                        if (fieldStyleShortcutConfig && fieldStyleShortcutConfig.properties && fieldStyleShortcutConfig.properties.length) {
                            const fieldStyleProp = fieldStyleShortcutConfig.properties.find(p => p.propertyID === 'fieldStyleConfig');
                            if (fieldStyleProp) {
                                fieldStyleProp.editorParams.propertyData = propertyData;
                                fieldStyleProp.editorParams.needClearConfig = true;
                            }
                        }

                        break;
                    }
                    default: {
                        // 联动修改列样式的快捷配置
                        if (changeObject.parentPropertyID === 'formatter') {

                            const fieldStyleShortcutConfig = self.propertyConfig.find(c => c.categoryId === 'fieldStyleShortcutConfig');
                            if (fieldStyleShortcutConfig && fieldStyleShortcutConfig.properties && fieldStyleShortcutConfig.properties.length) {
                                const fieldStyleProp = fieldStyleShortcutConfig.properties.find(p => p.propertyID === 'fieldStyleConfig');
                                if (fieldStyleProp) {
                                    fieldStyleProp.editorParams.propertyData = propertyData;
                                }
                            }
                        }
                    }
                }

                self.setGridFieldEditorPropSync(propertyData, changeObject);
            }
        };
    }
    /**
     * 组装列格式化属性
     */
    private getFormatterProps(propertyData: any): PropertyEntity[] {
        return [
            {
                propertyID: 'type',
                propertyName: '格式化类型',
                propertyType: 'select',
                description: '格式化类型选择',
                iterator: this.getDateFormatter(propertyData),
                refreshPanelAfterChanged: true
            },
            {
                propertyID: 'customFormat',
                propertyName: '自定义格式化方法',
                propertyType: 'modal',
                description: '自定义格式化方法设置',
                editor: CodeEditorComponent,
                visible: propertyData.formatter && propertyData.formatter.type === 'custom',
                group: 'custom',
                editorParams: {
                    language: 'javascript',
                    exampleCode:
                        '\r\n  (value, rowData) => {\r\n    return value + \'的奖金\';\r\n  }\r\n\r\n ' +
                        '注：\r\n  value：单元格数据  \r\n  rowData：行数据  \r\n'
                }
            },
            {
                propertyID: 'prefix',
                propertyName: '前置字符',
                propertyType: 'string',
                description: '数字前置字符设置',
                visible: propertyData.formatter && propertyData.formatter.type === 'number',
                group: 'number',
                refreshPanelAfterChanged: true
            },
            {
                propertyID: 'suffix',
                propertyName: '后置字符',
                propertyType: 'string',
                description: '数字后置字符设置',
                visible: propertyData.formatter && propertyData.formatter.type === 'number',
                group: 'number',
                refreshPanelAfterChanged: true
            },
            {
                propertyID: 'precision',
                propertyName: '精度',
                propertyType: 'number',
                description: '数字精度设置',
                decimals: 0,
                min: 0,
                defaultValue: 0,
                visible: propertyData.formatter && propertyData.formatter.type === 'number',
                group: 'number',
                refreshPanelAfterChanged: true
            },
            {
                propertyID: 'decimal',
                propertyName: '小数分隔符',
                propertyType: 'string',
                description: '数字小数分隔符设置',
                defaultValue: '.',
                visible: propertyData.formatter && propertyData.formatter.type === 'number',
                group: 'number',
                refreshPanelAfterChanged: true
            }, {
                propertyID: 'thousand',
                propertyName: '千分位',
                propertyType: 'string',
                description: '数字千分位设置',
                defaultValue: ',',
                visible: propertyData.formatter && propertyData.formatter.type === 'number',
                group: 'number',
                refreshPanelAfterChanged: true
            },
            {
                propertyID: 'trueText',
                propertyName: 'true文本',
                propertyType: 'string',
                description: 'true文本设置',
                visible: propertyData.formatter &&
                    (propertyData.formatter.type === 'boolean' || propertyData.formatter.type === 'boolean2'),
                group: 'boolean'
            },
            {
                propertyID: 'falseText',
                propertyName: 'false文本',
                propertyType: 'string',
                description: 'false文本设置',
                visible: propertyData.formatter &&
                    (propertyData.formatter.type === 'boolean' || propertyData.formatter.type === 'boolean2'),
                group: 'boolean'
            },
            {
                propertyID: 'dateFormat',
                propertyName: '日期格式',
                propertyType: 'string',
                description: '日期格式设置',
                visible: propertyData.formatter && propertyData.formatter.type === 'date',
                group: 'date',
                refreshPanelAfterChanged: true
            }
        ];
    }
    private getBehaviorProperties(propertyData: any, viewModelId: string, gridData: any): ElementPropertyConfig {
        const self = this;
        const enumDataConfig = this.getEnumDataConfig(propertyData, viewModelId);

        // 获取绑定字段类型
        let dgVMField;
        let dgVMFieldType;
        const dgViewModel = this.dgVMService.getDgViewModel(viewModelId);
        if (propertyData.binding && dgViewModel) {
            dgVMField = dgViewModel.fields.find(f => f.id === propertyData.binding.field);
            if (dgVMField) {
                dgVMFieldType = dgVMField.multiLanguage ? 'multiLanguage' : dgVMField.type.name;
            }
        }

        const behaviorProperties: PropertyEntity[] = [
            {
                propertyID: 'binding',
                propertyName: '绑定',
                propertyType: 'modal',
                description: '绑定的表单字段',
                editor: BindingEditorComponent,
                editorParams: {
                    viewModelId,
                    componentId: propertyData.componentId,
                    controlType: propertyData.type,
                    allowedBindingType: 'Form',
                    gridFielType: dgVMFieldType,
                    unusedOnly: true
                },
                converter: new BindingEditorConverter(),
                readonly: !dgVMFieldType // 失效的字段，不允许切换类型，只能删除
            },
            {
                propertyID: 'visible',
                propertyName: '是否可见',
                propertyType: 'modal',
                description: '运行时组件是否可见',
                ...this.getVisiblePropertyConfig(propertyData, viewModelId)
            },
            {
                propertyID: 'readonly',
                propertyName: '只读',
                description: '是否只读',
                ...this.getReadonlyPropertyConfig(propertyData, viewModelId)
            },
            {
                propertyID: 'multiLanguage',
                propertyName: '启用多语字段',
                propertyType: 'boolean',
                description: '是否启用多语字段',
                readonly: true
            },
            {
                propertyID: 'languages',
                propertyName: '语言列表',
                propertyType: 'modal',
                description: '语言列表设置',
                editor: ItemCollectionEditorComponent,
                editorParams: {
                    columns: [
                        { field: 'code', title: '编号', editor: { type: EditorTypes.TEXTBOX } },
                        { field: 'name', title: '名称', editor: { type: EditorTypes.TEXTBOX } }],
                    requiredFields: ['code', 'name'],
                    uniqueFields: ['code', 'name'],
                    modalTitle: '语言编辑器',
                    canEmpty: false
                },
                converter: new ItemCollectionConverter(),
                visible: propertyData.multiLanguage
            },
            {
                propertyID: 'enumData',
                propertyName: '枚举数据',
                propertyType: 'modal',
                description: '枚举数据设置',
                editor: ItemCollectionEditorComponent,
                converter: new ItemCollectionConverter(),
                ...enumDataConfig.editorConfig,
                visible: this.checkEnumDataVisible(propertyData)
            },

            {
                propertyID: 'frozen',
                propertyName: '固定列',
                propertyType: propertyData.controlSource === 'Farris' ? 'select' : 'boolean',
                description: '固定列选择',
                iterator: [
                    { key: 'none', value: '不固定' },
                    { key: 'left', value: '固定左侧' },
                    { key: 'right', value: '固定右侧' }
                ],
                readonly: propertyData.controlSource === 'Farris' && (gridData.groupable || gridData.enableHeaderGroup)
            },
            {
                propertyID: 'sortable',
                propertyName: '允许排序',
                propertyType: 'boolean',
                description: '是否允许排序',
            },
            {
                propertyID: 'enableFilter',
                propertyName: '允许过滤',
                propertyType: 'boolean',
                description: '是否允许过滤',
                defaultValue: false,
                readonly: gridData.filterType === 'none',
                visible: propertyData.controlSource === 'Farris'
            },
            {
                propertyID: 'aggregate',
                propertyName: '汇总合计',
                propertyType: 'cascade',
                visible: propertyData.controlSource === 'Kendo',
                cascadeConfig: [
                    {
                        propertyID: 'type',
                        propertyName: '合计类型',
                        propertyType: 'select',
                        description: '合计类型选择',
                        iterator: [{ key: 'none', value: '无' }, { key: 'sum', value: '求和' }, { key: 'count', value: '计数' }]
                    },
                    {
                        propertyID: 'aggrTemplate',
                        propertyName: '合计行模版',
                        propertyType: 'string',
                        description: '合计行模版设置',
                    }
                ],
            },
            {
                propertyID: 'localization',
                propertyName: '启用数据国际化',
                propertyType: 'boolean',
                description: '是否启用数据国际化',
                visible: this.checkLocalizationVisible(propertyData)
            },
            {
                propertyID: 'localizationType',
                propertyName: '数据国际化类型',
                propertyType: 'select',
                description: '数据国际化类型选择',
                visible: this.checkLocalizationVisible(propertyData) && propertyData.localization,
                controlSource: 'Farris',
                iterator: this.getLocalizationTypes(propertyData)
            },
            {
                propertyID: 'allowGrouping',
                propertyName: '允许分组',
                propertyType: 'boolean',
                description: '是否允许分组',
                visible: propertyData.controlSource === 'Farris'
            }
        ];

        return {
            categoryId: 'behavior',
            categoryName: '行为',
            properties: behaviorProperties,
            setPropertyRelates(changeObject: FormPropertyChangeObject, data, parameters: any) {
                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'binding': {
                        // 修改绑定后需要同步其他字段
                        self.updateControlDomAfterChangingBinding(propertyData, parameters, viewModelId);

                        // 刷新实体树
                        self.refreshFormService.refreshSchamaTree.next();
                        break;
                    }
                    case 'frozen': {
                        if (propertyData.controlSource === 'Farris') {
                            if (changeObject.propertyValue !== 'none') {
                                self.notifyService.warning('请确保列表未启用分组、未启用多表头！');
                            }
                        }
                        break;
                    }
                    case 'enumData': {
                        if (enumDataConfig.dynamicMappingKeys && parameters) {
                            propertyData.idField = parameters.valueField;
                            propertyData.textField = parameters.nameField;
                        }
                        changeObject.relateChangeProps = [{
                            propertyID: 'idField',
                            propertyValue: propertyData.idField
                        },
                        {
                            propertyID: 'textField',
                            propertyValue: propertyData.textField
                        }];

                        break;
                    }
                    case 'localization': {
                        const localizationType = this.properties.find(p => p.propertyID === 'localizationType');
                        if (localizationType) {
                            localizationType.visible = self.checkLocalizationVisible(propertyData) && changeObject.propertyValue;
                            localizationType.iterator = self.getLocalizationTypes(propertyData);
                        }
                        break;
                    }
                }

                self.setGridFieldEditorPropSync(propertyData, changeObject);
            }
        };
    }

    private getEventPropertyConfig(propertyData, viewModelId: string): ElementPropertyConfig {
        const domService = this.domService;
        const webCmdService = this.webCmdService;
        const formBasicService = this.formBasicService;
        const eventEditorService = this.eventEditorService;
        const eventList = [
            {
                label: 'linkedLabelClick',
                name: '标签超链事件'
            }
        ];
        const self = this;
        return {
            categoryId: 'eventsEditor',
            categoryName: '事件',
            hideTitle: true,
            properties: EventsEditorFuncUtils.formProperties(eventEditorService, formBasicService, domService, webCmdService, propertyData, viewModelId, eventList),
            tabId: 'commands',
            tabName: '交互',
            setPropertyRelates(changeObject, data, parameters) {
                delete propertyData[viewModelId];
                if (parameters) {
                    parameters.setPropertyRelates = this.setPropertyRelates; // 添加自定义方法后，调用此回调方法，用于处理联动属性
                    parameters.controlInfo = { type: (propertyData.binding && propertyData.binding.path) || propertyData.type, name: propertyData.caption };  // 暂存控件信息，用于自动创建新方法的方法编号和名称

                    EventsEditorFuncUtils.saveRelatedParameters(eventEditorService, domService, webCmdService, propertyData, viewModelId, eventList, parameters);
                    this.properties = EventsEditorFuncUtils.formProperties(eventEditorService, formBasicService, domService, webCmdService, propertyData, viewModelId, eventList);
                }

                // 联动修改【启用标签超链接】属性
                const previousLinkedLabelEnabled = propertyData.linkedLabelEnabled;
                propertyData.linkedLabelEnabled = !!propertyData.linkedLabelClick;
                if (!previousLinkedLabelEnabled && propertyData.linkedLabelEnabled) {
                    self.notifyService.warning('启用标签超链事件后，列模板失效！');
                }
            }
        };
    }

    /**
     * 枚举类型字段，在变更列模板后需要重置图标配置数据
     * @param propertyData 列数据
     * @param changeObject 属性变更集
     * @param parameters 变更参数
     */
    private clearIconConfigAfterColTemplateChanged(propertyData: any, changeObject: FormPropertyChangeObject, parameters: any) {
        if (propertyData.dataType !== 'enum' || !propertyData.iconConfigForEnumData) {
            return;
        }

        if (changeObject.propertyValue !== parameters.oldValue) {
            propertyData.iconConfigForEnumData = null;
            this.notifyService.warning('变更列模板后，自动重置列样式快捷配置！');
        }
    }
    /**
     * Farris 列 分组合计属性
     * @param propertyData 属性值
     */
    private getGroupAggregateProperties(propertyData: any) {
        const self = this;
        const groupProperties: PropertyEntity[] = [
            {
                propertyID: 'type',
                propertyName: '合计类型',
                propertyType: 'select',
                description: '合计类型选择',
                iterator: [{ key: 'none', value: '无' }, { key: 'sum', value: '求和' }]
            },
            {
                propertyID: 'aggrTemplate',
                propertyName: '合计行文本',
                propertyType: 'string',
                description: '合计行文本设置',
                visible: propertyData.groupAggregate && propertyData.groupAggregate.type === 'none'
            },
            {
                propertyID: 'align',
                propertyName: '对齐方式',
                propertyType: 'select',
                description: '对齐方式选择',
                iterator: [{ key: 'left', value: '靠左' }, { key: 'center', value: '居中' }, { key: 'right', value: '靠右' }],
                defaultValue: 'left'
            },
            {
                propertyID: 'styler',
                propertyName: '单元格样式',
                propertyType: 'modal',
                description: '单元格样式设置',
                editor: CodeEditorComponent,
                editorParams: {
                    language: 'javascript',
                    exampleCode:
                        '\r\n(value, rowData, rowIndex) => {\r\n    return {\r\n        style: {\r\n' +
                        '            \'color\': \'red\',\r\n            \'font-weight\': 800\r\n        }\r\n    };' +
                        '\r\n}\r\n\r\n\r\n注：\r\n  value：单元格数据  \r\n  rowData：行数据  \r\n  rowIndex：当前行索引'
                }
            },
            {
                propertyID: 'formatter',
                propertyName: '数据格式化',
                propertyType: 'cascade',
                description: '数据格式化设置',
                visible: propertyData.groupAggregate && propertyData.groupAggregate.type !== 'none',
                cascadeConverter: new GridFieldFormatterConverter(),
                cascadeConfig: [{
                    propertyID: 'type',
                    propertyName: '格式化类型',
                    propertyType: 'select',
                    description: '格式化类型选择',
                    iterator: [
                        { key: 'none', value: '无' },
                        { key: 'number', value: '数字' },
                        { key: 'custom', value: '自定义' }]
                },
                {
                    propertyID: 'customFormat',
                    propertyName: '自定义格式化方法',
                    propertyType: 'modal',
                    description: '自定义格式化方法设置',
                    editor: CodeEditorComponent,
                    group: 'custom',
                    visible: propertyData.groupAggregate && propertyData.groupAggregate.type !== 'none' &&
                        propertyData.groupAggregate.formatter && propertyData.groupAggregate.formatter.type === 'custom',
                    editorParams: {
                        language: 'javascript',
                        exampleCode:
                            '\r\n  (value, rowData) => {\r\n    return value + \'的奖金\';\r\n  }\r\n\r\n ' +
                            '注：\r\n  value：单元格数据  \r\n  rowData：行数据  \r\n'
                    }
                },
                {
                    propertyID: 'prefix',
                    propertyName: '前置字符',
                    propertyType: 'string',
                    description: '数字前置字符',
                    group: 'number',
                    visible: propertyData.groupAggregate && propertyData.groupAggregate.type !== 'none' &&
                        propertyData.groupAggregate.formatter && propertyData.groupAggregate.formatter.type === 'number'
                },
                {
                    propertyID: 'suffix',
                    propertyName: '后置字符',
                    propertyType: 'string',
                    description: '数字后置字符',
                    group: 'number',
                    visible: propertyData.groupAggregate && propertyData.groupAggregate.type !== 'none' &&
                        propertyData.groupAggregate.formatter && propertyData.groupAggregate.formatter.type === 'number'
                },
                {
                    propertyID: 'precision',
                    propertyName: '精度',
                    propertyType: 'number',
                    description: '数字精度设置',
                    decimals: 0,
                    min: 0,
                    group: 'number',
                    defaultValue: 0,
                    visible: propertyData.groupAggregate && propertyData.groupAggregate.type !== 'none' &&
                        propertyData.groupAggregate.formatter && propertyData.groupAggregate.formatter.type === 'number'
                },
                {
                    propertyID: 'decimal',
                    propertyName: '小数分隔符',
                    propertyType: 'string',
                    description: '数字小数分隔符设置',
                    defaultValue: '.',
                    group: 'number',
                    visible: propertyData.groupAggregate && propertyData.groupAggregate.type !== 'none' &&
                        propertyData.groupAggregate.formatter && propertyData.groupAggregate.formatter.type === 'number'
                }, {
                    propertyID: 'thousand',
                    propertyName: '千分位',
                    propertyType: 'string',
                    description: '数字千分位设置',
                    defaultValue: ',',
                    group: 'number',
                    visible: propertyData.groupAggregate && propertyData.groupAggregate.type !== 'none' &&
                        propertyData.groupAggregate.formatter && propertyData.groupAggregate.formatter.type === 'number'
                }]
            }
        ];
        return {
            categoryId: 'groupAggregate',
            categoryName: '分组合计',
            properties: groupProperties,
            propertyData: propertyData.groupAggregate,
            enableCascade: true,
            parentPropertyID: 'groupAggregate',
            setPropertyRelates(changeObject: FormPropertyChangeObject, propData, parameters) {

                switch (changeObject.propertyID) {
                    case 'type': {

                        if (!changeObject.parentPropertyID) {
                            // 切换合计类型
                            const formatter = this.properties.find(p => p.propertyID === 'formatter');
                            if (formatter) {
                                formatter.visible = changeObject.propertyValue !== 'none';
                            }
                            const aggrTemplate = this.properties.find(p => p.propertyID === 'aggrTemplate');
                            if (aggrTemplate) {
                                aggrTemplate.visible = changeObject.propertyValue === 'none';
                            }

                        } else if (changeObject.parentPropertyID === 'formatter') {
                            // 切换格式化类型
                            const formatter = this.properties.find(p => p.propertyID === 'formatter');
                            if (formatter && formatter.cascadeConfig) {
                                formatter.cascadeConfig.filter(p => p.group).forEach(p => {
                                    p.visible = p.group === changeObject.propertyValue;
                                });
                            }
                            propData.formatter = self.setDataGridFormatterDefaults(changeObject.propertyValue, propData.formatter);
                        }

                        break;
                    }
                }



            }
        };
    }

    /**
     * 汇总合计属性
     * @param propertyData 属性值
     */
    private getAggregateProperties(propertyData: any) {
        const self = this;
        const aggregateProperties: PropertyEntity[] = [
            {
                propertyID: 'type',
                propertyName: '合计类型',
                propertyType: 'select',
                description: '合计类型选择',
                iterator: [{ key: 'none', value: '无' }, { key: 'sum', value: '求和' }, { key: 'count', value: '计数' },
                { key: 'max', value: '最大值' }, { key: 'min', value: '最小值' }, { key: 'average', value: '平均值' }]
            },
            {
                propertyID: 'aggrTemplate',
                propertyName: '合计行文本',
                propertyType: 'string',
                description: '合计行文本设置',
                visible: propertyData.aggregate && propertyData.aggregate.type === 'none'
            },
            {
                propertyID: 'align',
                propertyName: '对齐方式',
                propertyType: 'select',
                description: '对齐方式选择',
                iterator: [{ key: 'left', value: '靠左' }, { key: 'center', value: '居中' }, { key: 'right', value: '靠右' }],
                defaultValue: 'left'
            },
            {
                propertyID: 'styler',
                propertyName: '单元格样式',
                propertyType: 'modal',
                description: '单元格样式设置',
                editor: CodeEditorComponent,
                editorParams: {
                    language: 'javascript',
                    exampleCode:
                        '\r\n(value, rowData, rowIndex) => {\r\n    return {\r\n        style: {\r\n' +
                        '            \'color\': \'red\',\r\n            \'font-weight\': 800\r\n        }\r\n    };' +
                        '\r\n}\r\n\r\n\r\n注：\r\n  value：单元格数据  \r\n  rowData：行数据  \r\n  rowIndex：当前行索引'
                }
            },
            {
                propertyID: 'formatter',
                propertyName: '数据格式化',
                propertyType: 'cascade',
                description: '数据格式化设置',
                visible: propertyData.aggregate && propertyData.aggregate.type !== 'none',
                cascadeConverter: new GridFieldFormatterConverter(),
                cascadeConfig: [{
                    propertyID: 'type',
                    propertyName: '格式化类型',
                    propertyType: 'select',
                    description: '格式化类型选择',
                    iterator: [
                        { key: 'none', value: '无' },
                        { key: 'number', value: '数字' },
                        { key: 'custom', value: '自定义' }]
                },
                {
                    propertyID: 'customFormat',
                    propertyName: '自定义格式化方法',
                    propertyType: 'modal',
                    description: '自定义格式化方法设置',
                    editor: CodeEditorComponent,
                    group: 'custom',
                    visible: propertyData.aggregate && propertyData.aggregate.type !== 'none' && propertyData.aggregate.formatter
                        && propertyData.aggregate.formatter.type === 'custom',
                    editorParams: {
                        language: 'javascript',
                        exampleCode:
                            '\r\n  (value, rowData) => {\r\n    return value + \'的奖金\';\r\n  }\r\n\r\n ' +
                            '注：\r\n  value：单元格数据  \r\n  rowData：行数据  \r\n'
                    }
                },
                {
                    propertyID: 'prefix',
                    propertyName: '前置字符',
                    propertyType: 'string',
                    description: '数字前置字符',
                    group: 'number',
                    visible: propertyData.aggregate && propertyData.aggregate.type !== 'none' && propertyData.aggregate.formatter
                        && propertyData.aggregate.formatter.type === 'number'
                },
                {
                    propertyID: 'suffix',
                    propertyName: '后置字符',
                    propertyType: 'string',
                    description: '数字后置字符',
                    group: 'number',
                    visible: propertyData.aggregate && propertyData.aggregate.type !== 'none' && propertyData.aggregate.formatter
                        && propertyData.aggregate.formatter.type === 'number'
                },
                {
                    propertyID: 'precision',
                    propertyName: '精度',
                    propertyType: 'number',
                    description: '数字精度设置',
                    decimals: 0,
                    min: 0,
                    group: 'number',
                    defaultValue: 0,
                    visible: propertyData.aggregate && propertyData.aggregate.type !== 'none' && propertyData.aggregate.formatter
                        && propertyData.aggregate.formatter.type === 'number'
                },
                {
                    propertyID: 'decimal',
                    propertyName: '小数分隔符',
                    propertyType: 'string',
                    description: '数字小数分隔符设置',
                    defaultValue: '.',
                    group: 'number',
                    visible: propertyData.aggregate && propertyData.aggregate.type !== 'none' && propertyData.aggregate.formatter
                        && propertyData.aggregate.formatter.type === 'number'
                }, {
                    propertyID: 'thousand',
                    propertyName: '千分位',
                    propertyType: 'string',
                    description: '数字千分位设置',
                    defaultValue: ',',
                    group: 'number',
                    visible: propertyData.aggregate && propertyData.aggregate.type !== 'none' && propertyData.aggregate.formatter
                        && propertyData.aggregate.formatter.type === 'number'
                }]
            }
        ];
        return {
            categoryId: 'GridAggregate',
            categoryName: '汇总合计',
            properties: aggregateProperties,
            propertyData: propertyData.aggregate,
            enableCascade: true,
            parentPropertyID: 'aggregate',
            setPropertyRelates(changeObject, propData, parameters) {
                if (changeObject.propertyID !== 'type') {
                    return;
                }
                if (!changeObject.parentPropertyID) {
                    // 切换合计类型
                    const formatter = this.properties.find(p => p.propertyID === 'formatter');
                    if (formatter) {
                        formatter.visible = changeObject.propertyValue !== 'none';
                    }
                    const aggrTemplate = this.properties.find(p => p.propertyID === 'aggrTemplate');
                    if (aggrTemplate) {
                        aggrTemplate.visible = changeObject.propertyValue === 'none';
                    }

                } else if (changeObject.parentPropertyID === 'formatter') {
                    // 切换格式化类型
                    const formatter = this.properties.find(p => p.propertyID === 'formatter');
                    if (formatter && formatter.cascadeConfig) {
                        formatter.cascadeConfig.filter(p => p.group).forEach(p => {
                            p.visible = p.group === changeObject.propertyValue;
                        });
                    }
                    propData.formatter = self.setDataGridFormatterDefaults(changeObject.propertyValue, propData.formatter);
                }
            }
        };
    }

    /**
     * farris datagrid 列 设置格式默认值
     * @param type 格式化类型
     * @param col 列格式值
     */
    private setDataGridFormatterDefaults(type: string, col: any) {
        switch (type) {
            case 'number': {
                col = Object.assign({
                    precision: 0,
                    thousand: ',',
                    prefix: '',
                    suffix: '',
                    decimal: '.'
                }, col);
                break;
            }
            case 'boolean': {
                col = Object.assign(col, {
                    trueText: '是',
                    falseText: '否'
                });
                break;
            }
            case 'boolean2': {
                col = Object.assign(col, {
                    trueText: '<span class="f-icon f-icon-checkbox-checked f-datagrid-default-show-icon"></span>',
                    falseText: '<span class="f-icon f-icon-checkbox f-datagrid-default-show-icon"></span>'
                });
                break;
            }
            case 'date': {
                col = Object.assign({
                    dateFormat: 'yyyy-MM-dd',
                }, col);
                break;
            }
            case 'none': {
                col = {
                    type: 'none'
                };
            }
        }
        return col;
    }


    /**
     * 设置列表列和编辑器的属性联动(目前树表没有列编辑器)
     * @param propertyData 属性值
     * @param changeObject 变更集
     */
    private setGridFieldEditorPropSync(propertyData: any, changeObject: FormPropertyChangeObject) {
        // 同步列编辑器
        if (propertyData.editor) {
            if (changeObject.propertyID === 'format' || changeObject.propertyID === 'languages') {
                propertyData.editor[changeObject.propertyID] = changeObject.propertyValue;
            }
            if (changeObject.propertyID === 'enumData') {
                propertyData.editor.enumData = changeObject.propertyValue;
                propertyData.editor.idField = propertyData.idField;
                propertyData.editor.textField = propertyData.textField;
            }

        }

    }
    /**
     * 修改绑定后要同步变更控件path等属性，若是帮助控件还要变更数据源属性并同步viewModel
     */
    updateControlDomAfterChangingBinding(propertyData: any, parameters: any, viewModelId: string) {
        const selectedData = parameters && parameters.selectedData;
        if (!selectedData) {
            return;
        }

        // 变更dataField和path属性
        propertyData.dataField = selectedData.bindingPath;
        propertyData.path = selectedData.bindingPath;

        if (!propertyData.editor) {
            return;
        }

        // 同步列编辑器
        propertyData.editor.binding = propertyData.binding;
        propertyData.editor.path = selectedData.bindingPath;


        // 帮助控件变更dataSource.uri属性
        if (propertyData.editor.type === DgControl.LookupEdit.type && propertyData.editor.dataSource && propertyData.editor.dataSource.uri) {
            const uri = propertyData.editor.dataSource.uri;
            const index = uri.indexOf('.');
            if (index < 0) {
                return;
            }

            if (propertyData.editor.binding.type === FormBindingType.Form) {
                const newUri = uri.slice(0, index) + '.' + selectedData.bindingField;
                propertyData.editor.dataSource.uri = newUri;

                // 同步viewModel Field
                const dgViewModel = this.dgVMService.getDgViewModel(viewModelId);
                dgViewModel.changeField(propertyData.binding.field, { editor: { dataSource: propertyData.editor.dataSource } });
            }

        }
    }
    /**
     * 枚举数据的编辑器不同：
     * kendo的控件确定只有value-name键值
     * farris的控件若绑定了枚举字段只有value-name 键值；若绑定了变量或者字符串字段则可以自行指定idField 和textField
     */
    private getEnumDataConfig(fieldData: any, viewModelId: string): { editorConfig: any, dynamicMappingKeys: boolean } {
        if (!fieldData.binding) {
            return { editorConfig: null, dynamicMappingKeys: false };
        }

        const editorConfig: any = {
            editorParams: {
                columns: [
                    { field: 'value', title: '枚举值', editor: { type: EditorTypes.TEXTBOX } },
                    { field: 'name', title: '枚举名称', editor: { type: EditorTypes.TEXTBOX } },
                ],
                requiredFields: ['value', 'name'],
                uniqueFields: ['value', 'name'],
                modalTitle: '枚举编辑器',
                canEmpty: true
            }
        };
        if (fieldData.controlSource !== 'Farris' || (fieldData.editor && fieldData.editor.controlSource !== 'Farris')) {
            return { editorConfig, dynamicMappingKeys: false };
        }
        // 绑定枚举字段的 下拉控件，编辑器只支持value-name
        if (fieldData.dataType === 'enum') {
            return { editorConfig, dynamicMappingKeys: false };
        }

        // 绑定字符串的下拉控件，枚举的键值可以自定义
        editorConfig.editorParams.dynamicMappingKeys = true;
        if (fieldData.editor) {
            editorConfig.editorParams.valueField = fieldData.idField || fieldData.editor.idField;
            editorConfig.editorParams.nameField = fieldData.textField || fieldData.editor.textField;
        } else {
            editorConfig.editorParams.valueField = fieldData.idField;
            editorConfig.editorParams.nameField = fieldData.textField;
        }


        return { editorConfig, dynamicMappingKeys: true };
    }

    private checkEnumDataVisible(propertyData: any): boolean {
        // 多语字段：不展示枚举属性
        if (propertyData.multiLanguage) {
            return false;
        }
        // 枚举字段：展示
        if (propertyData.dataType === 'enum') {
            return true;
        }
        // 字符串字段：配置成枚举控件，展示
        if (propertyData.dataType === 'string') {
            if (!propertyData.editor) {
                return true;
            } else if (propertyData.editor && propertyData.editor.type === DgControl.EnumField.type) {
                return true;
            }
        }
        return false;
    }

    private getLocalizationTypes(propertyData: any): KeyMap[] {
        switch (propertyData.dataType) {
            case GridFieldDataType.date: {
                return [{ key: 'Date', value: '日期' }];
            }
            case GridFieldDataType.datetime: {
                return [{ key: 'DateTime', value: '日期时间' }];
            }
            default: {
                return [{ key: 'Date', value: '日期' }, { key: 'DateTime', value: '日期时间' }];
            }
        }
    }

    /**
     * 限定数据国际化类型属性展示范围：
     * 1、日期、日期时间类型字段---显示
     * 2、可编辑的列表:编辑器配置成了日期控件---显示
     * 3、不可编辑的列表：格式化属性配置成日期---显示
     */
    private checkLocalizationVisible(propertyData: any): boolean {
        if (propertyData.controlSource !== 'Farris') {
            return false;
        }
        switch (propertyData.dataType) {
            // 日期类型字段
            case 'date': case 'datetime': {
                return true;
            }
            // 字符串类型字段
            case 'string': {
                // 可编辑列表
                if (propertyData.editor && propertyData.editor.type === DgControl.DateBox.type) {
                    return true;
                }
                // 不可编辑列表
                if (!propertyData.editor && propertyData.formatter && propertyData.formatter.type === 'date') {
                    return true;
                }
            }
        }
        return false;
    }

    private getReadonlyPropertyConfig(propertyData: any, viewModelId: string) {
        if (propertyData.controlSource === 'Farris') {
            return {
                propertyType: 'modal',
                editor: JavaScriptBooleanEditorComponent,
                converter: new JavaScriptBooleanConverter(this.domService, propertyData.binding),
                editorParams: {
                    modalTitle: '只读编辑器',
                    viewModelId,
                    showExpression: true,
                    bindingFieldId: propertyData.binding.field,
                    expressionType: 'readonly',
                    showJavascript: true,
                    exampleCode: '(rowData) => { \r\n    // ...\r\n    return true;\r\n}\r\n参数：\r\n' +
                        'rowData：行数据\r\n\r\n\r\n函数返回布尔类型：\r\ntrue: 只读\r\nfalse: 可编辑'

                }
            };
        } else {
            return {
                propertyType: 'editableSelect',
                iterator: [{ key: true, value: 'true' }, { key: false, value: 'false' }]
            };

        }

    }

    private getVisiblePropertyConfig(propertyData: any, viewModelId: string) {
        const visibleProp = this.getVisiblePropertyEntity(propertyData, viewModelId);
        if (propertyData.controlSource === 'Farris') {
            return {
                editor: JavaScriptBooleanEditorComponent,
                converter: new JavaScriptBooleanConverter(this.domService, propertyData.binding),
                editorParams: {
                    modalTitle: '可见编辑器',
                    viewModelId,
                    showExpression: true,
                    bindingFieldId: propertyData.binding.field,
                    expressionType: 'visible',
                    showJavascript: true,
                    exampleCode: '(rowData) => { \r\n    // ...\r\n    return true;\r\n}\r\n\r\n参数：\r\nrowData：行数据' +
                        '\r\n\r\n\r\n函数返回布尔类型：\r\ntrue: 可见\r\nfalse: 隐藏'

                }
            };
        } else {
            return visibleProp;

        }

    }
    /**
     * 获取列格式化类型
     */
    private getDateFormatter(propertyData: any) {

        const iterator = [
            { key: 'none', value: '无' },
            { key: 'number', value: '数字' },
            { key: 'boolean', value: '布尔-文本' },
            { key: 'boolean2', value: '布尔-图标' },
            { key: 'date', value: '日期' },
            { key: 'enum', value: '枚举' },
            { key: 'custom', value: '自定义' }
        ];

        // 绑定字段为日期时，支持相对时间格式
        if (propertyData.dataType === GridFieldDataType.date || propertyData.dataType === GridFieldDataType.datetime) {
            const timego = { key: 'timeago', value: '相对时间' };
            iterator.splice(5, 0, timego);
        }

        return iterator;
    }

}
